#ifndef AFCORE_COMMON_LOG_LOG_HUB_
#define AFCORE_COMMON_LOG_LOG_HUB_

#include <unordered_map>
#include <mutex>
#include <functional>
#include <memory>

#include "logcommon.h"
#include "nocopyable.h"
#include "helper_loglevel.h"
#include "duration.h"

namespace afcore {

/// @brief  日志
namespace log {

class CPeriodicWorker;

/// @brief  日志中枢
class CLogHub
  : public CNocopyable {
public:
  /// @brief  单例
  /// @return 全局日志中枢
  static CLogHub& Instance();

  /// @brief  注册记录器
  /// @param  new_logger      记录器
  void RegisterLogger(RLoggerSptr new_logger);

  /// @brief  初始化记录器
  /// @param  new_logger      记录器
  void InitializeLogger(RLoggerSptr new_logger);

  /// @brief  获得原生的记录器指针
  /// @return 原生的记录器指针
  CLogger* GetDefaultRaw();

  /// @brief  通过记录器的名字获取记录器
  /// @return 记录器
  RLoggerSptr GetLoggerByName(const std::string& logger_name);

  /// @brief  获取默认的记录器
  /// @return 默认的记录器
  RLoggerSptr GetDefaultLogger();

  /// @brief  设置默认的记录器
  /// @param  new_default_logger    新的默认记录器
  void SetDefaultLogger(RLoggerSptr new_default_logger);

  /// @brief  设置线程池
  /// @param  tp              线程池
  void SetThreadPool(RAsyncThreadPoolSptr tp);

  /// @brief  设置格式器
  /// @param  formatter       格式器
  void SetFormatter(RFormatterUptr formatter);

  /// @brief  获取线程池
  /// @return 线程池
  RAsyncThreadPoolSptr GetThreadPool();

  /// @brief  设置追踪器可用
  /// @param  n_messages      最大记录深度
  void EnableBacktrace(size_t n_messages);

  /// @brief  设置追踪器不可用
  void DisableBacktrace();

  /// @brief  设置记录器最低日志级别
  /// @param  log_level       最低日志级别
  void SetLogLevel(ELogLevel log_level);

  /// @brief  指定级别刷新
  /// @param  log_level       刷新级别日志级别
  void SetFlushLevel(ELogLevel log_level);

  /// @brief  指定间隔刷新所有记录器
  /// @param  interval        刷新间隔
  void FlushEvery(RSeconds interval);

  /// 设置错误处理
  /// @param  handler         错误处理程序
  void SetErrorHander(RErrHanlder handler);

  /// @brief  所有记录器执行函数操作
  /// @param  fun             记录器要执行的操作
  void ApplyAll(const std::function<void(const RLoggerSptr)>& fun);

  /// @brief  刷新所有记录器
  void FlushAll();

  /// @brief  丢弃指定名称的记录器
  /// @param  logger_name     要丢弃的记录器名称
  void Drop(const std::string& logger_name);

  /// @brief  丢弃所有记录器
  void DropAll();

  /// @brief  关闭
  void Shutdown();

  /// @brief  获取线程池互斥锁
  /// @return 线程池互斥锁
  std::recursive_mutex& GetTpMutex();

  /// @brief  设置自动注册标志
  void SetAutomaticRegistration(bool automatic_registration);

  /// @brief  更新日志记录器级别
  void UpdateLevels(CHelperLogLevel levels);

private:
  /// @brief  构造函数
  CLogHub();
  /// @brief  析构函数
  ~CLogHub() = default;

  /// @brief  如果该名称的记录器存在则抛出异常
  /// @param  logger_name         要注册的记录器名称
  void ThrowIfExists(const std::string& logger_name);

  /// @brief  注册记录器(内用)
  /// @param  new_logger      记录器
  void DoRegisterLogger(RLoggerSptr new_logger);

private:
  std::mutex flush_mutex_;                                  ///< 刷新互斥锁
  std::mutex logger_map_mutex_;                             ///< 记录器互斥锁
  std::recursive_mutex tp_mutex_;                           ///< 线程池互斥锁
  std::unordered_map<std::string, RLoggerSptr> loggers_;    ///< 记录器 key 记录器名称
  CHelperLogLevel levels_;                                  ///< 记录器级别
  RFormatterUptr formatter_;                                ///< 格式器
  ELogLevel flush_level_ {kLogLevelOff};                    ///< 刷新级别
  RErrHanlder err_handler_;                                 ///< 错误处理程序
  RAsyncThreadPoolSptr tp_;                                 ///< 异步线程池
  RPeriodicWorkerUptr periodic_flusher_;                    ///< 周期工作线程
  RLoggerSptr default_logger_;                              ///< 默认记录器
  bool automatic_registration_ {true};                      ///< 自动注册标志
  size_t backtrace_n_messages_ {0};                         ///< 追溯器容量
};

} // !namespace log

} // !namespace afcore

#endif //! AFCORE_COMMON_LOG_LOG_HUB_